package api

import (
	"encoding/json"
	"fmt"
	"github.com/duke-git/lancet/v2/convertor"
	"github.com/imroc/req/v3"
	"github.com/pkg/errors"
	"github.com/tidwall/gjson"
	"pkg/stock/typeutil"
	"systray/internel/pkg/stock/indicators"

	"strings"
	"time"
)

type Tencent struct {
}

// Realtime 实时数据
// 返回值对应的字段 https://blog.51cto.com/u_15127704/4740983
func (t Tencent) Realtime(codes []Code) (map[string]typeutil.Kline, error) {
	// 简要信息, 需要拼接 s_, q=s_sh000001,s_sz000001
	var codeIds []string
	for _, info := range codes {
		codeIds = append(codeIds, fmt.Sprintf("%s%s", info.Exchange, info.Symbol))
	}

	resp, err := req.DefaultClient().R().SetQueryParam("q", strings.Join(codeIds, ",")).Get("https://qt.gtimg.cn")
	if err != nil {
		return nil, err
	}

	data := make(map[string]typeutil.Kline, len(codeIds))

	// 先去除最后的分号, 再分割
	rows := strings.Split(strings.TrimRight(resp.String(), ";\n"), ";")
	for _, row := range rows {
		// 去除换行符, 再分割
		fields := strings.Split(strings.Trim(row, "\n"), "~")

		code := fields[0][2:10]
		timestamp, _ := time.Parse("20060102150405", fields[30])
		data[code] = typeutil.Kline{
			Symbol:              code,
			ClosePrice:          t.toFloat(fields[3]),
			YesterdayClosePrice: t.toFloat(fields[4]),
			OpenPrice:           t.toFloat(fields[5]),
			Timestamp:           timestamp,
			IncreasePercentage:  t.toFloat(fields[32]),
			HighPrice:           t.toFloat(fields[33]),
			LowPrice:            t.toFloat(fields[34]),
			TradeVolume:         t.toFloat(fields[36]),
			TradeAmount:         t.toFloat(fields[37]),
			TurnoverRate:        t.toFloat(fields[38]),
			Amplitude:           t.toFloat(fields[43]),
		}
	}

	return data, nil
}

// Minute 分钟线
func (t Tencent) Minute(minute int, codes []Code) (map[string][]typeutil.Kline, error) {
	var codeIds []string
	for _, info := range codes {
		codeIds = append(codeIds, fmt.Sprintf("%s%s", info.Exchange, info.Symbol))
	}

	var data = make(map[string][]typeutil.Kline, len(codeIds))
	for _, code := range codeIds {
		resp, err := req.DefaultClient().R().SetQueryParam("param", fmt.Sprintf("%s,m%d,,420", code, minute)).Get("https://ifzq.gtimg.cn/appstock/app/kline/mkline")
		if err != nil {
			return nil, errors.Wrap(err, "获取分时错误")
		}

		items := gjson.GetBytes(resp.Bytes(), fmt.Sprintf("data.%s.m%d", code, minute)).Array()

		// ["202309051030","0.798","0.801","0.803","0.794","2401930.690",{},"485.5195"]
		// 0 时间, 1 开盘价, 2 收盘价, 3 最高价, 4 最低价, 5 量能, 6 {}, 7 换手率（需要除100）
		// 计算平均

		var klines []typeutil.Kline
		for i, item := range items {
			var arr []string
			_ = json.Unmarshal([]byte(item.String()), &arr)

			timestamp, _ := time.Parse("200601021504", arr[0])
			yesterdayClosePrice := 0.0
			if i > 0 {
				yesterdayClosePrice = klines[i-1].ClosePrice
			}
			klines = append(klines, typeutil.Kline{
				Symbol:              code,
				Timestamp:           timestamp,
				OpenPrice:           t.toFloat(arr[1]),
				ClosePrice:          t.toFloat(arr[2]),
				YesterdayClosePrice: yesterdayClosePrice,
				HighPrice:           t.toFloat(arr[3]),
				LowPrice:            t.toFloat(arr[4]),
				TradeVolume:         t.toFloat(arr[5]),
				IncreasePercentage:  t.toFloat(arr[5]) * t.toFloat(arr[2]),
				TurnoverRate:        t.toFloat(arr[7]) / 100,
			})
		}

		klines = indicators.MA(klines, []int{30, 60})
		klines = indicators.CCI(klines, 14)

		data[code] = klines
	}

	return data, nil
}

func (t Tencent) toFloat(v string) float64 {
	f, _ := convertor.ToFloat(v)
	return f
}
